#pragma once

#include <stdlib.h>
#include <chrono>
#include <iostream>
#include <sstream>

#define BIG_LITTLE_SWAP16(x)        ( (((*(short int *)&x) & 0xff00) >> 8) | \
                                      (((*(short int *)&x) & 0x00ff) << 8) )

#define BIG_LITTLE_SWAP32(x)        ( (((*(long int *)&x) & 0xff000000) >> 24) | \
                                      (((*(long int *)&x) & 0x00ff0000) >> 8) | \
                                      (((*(long int *)&x) & 0x0000ff00) << 8) | \
                                      (((*(long int *)&x) & 0x000000ff) << 24) )

#define BIG_LITTLE_SWAP64(x)        ( (((*(long long int *)&x) & 0xff00000000000000) >> 56) | \
                                      (((*(long long int *)&x) & 0x00ff000000000000) >> 40) | \
                                      (((*(long long int *)&x) & 0x0000ff0000000000) >> 24) | \
                                      (((*(long long int *)&x) & 0x000000ff00000000) >> 8) | \
                                      (((*(long long int *)&x) & 0x00000000ff000000) << 8) | \
                                      (((*(long long int *)&x) & 0x0000000000ff0000) << 24) | \
                                      (((*(long long int *)&x) & 0x000000000000ff00) << 40) | \
                                      (((*(long long int *)&x) & 0x00000000000000ff) << 56) )

namespace SC {
	template<typename T, size_t N>
	constexpr size_t arraySize(const T(&)[N]) {
		return N;
	}

	inline short bigLittleSwap(short avValue) {
		return _byteswap_ushort(avValue);
	}

	inline long bigLittleSwap(long avValue) {
		return _byteswap_ulong(avValue);
	}

	inline long long bigLittleSwap(long long avValue) {
		return _byteswap_uint64(avValue);
	}

	inline int64_t makeInt64(int32_t high, int32_t low) {
		return (static_cast<int64_t>(high) << 32) | static_cast<uint32_t>(low);
	}

	static void randomBytes(uint8_t* data, int len)
	{
		srand((unsigned int)std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count());
		int randomData;
		for (int i = 0; i < len; ++i)
		{
			randomData = rand() % 127 + 1;
			data[i] = randomData;
		}
	}

	inline int32_t randomInt32(const int32_t avValue, const uint8_t avFloatPoint) {
		int32_t lvTmp = avValue * avFloatPoint / 100;
		return avValue + (rand() * rand() % (lvTmp * 2 + 1) - lvTmp);
	}

	std::string getDateTime();

	template<typename... Args>
	void log(Args&&... args) {
#ifdef _DEBUG
		std::ostringstream oss;
		(oss << ... << std::forward<Args>(args));
		std::cout << getDateTime() << oss.str() << std::endl;
#endif
	}


	char* wChar2Char(wchar_t* data, bool freeOld);
	wchar_t* Char2WChar(char* data, bool freeOld);
	void int64_to_mac_string(long long macInt, char* macString, int bufLen);
}